#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>  
#include <linux/of_gpio.h>
#include <linux/gpio.h>
int gpio;
struct device_node	*nd;

int LED_probe(struct platform_device *pdev){
    printk("probe已加载\r\n");
    nd = of_find_node_by_path("/led_001");
    if(nd == NULL){
        printk("节点加载错误\r\n");
        return -1;
    }
    gpio = of_get_named_gpio(nd,"gpios",0);
    if(gpio < 0){
        printk("gpio编号获取失败\r\n");
        return -1;
    }
    int ret = 0;
    ret =  gpio_direction_output(gpio,0);
    if(ret < 0){
        printk("io设置失败\r\n");
        return -1;
    }
    return 0;
}

int LED_remove(struct platform_device *pdev){
        return 0;
}

struct platform_driver LED_platform_driver = {
    .probe = LED_probe,
    .remove = LED_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name  = "led_001",
    },
};

ssize_t LED_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t){
    int ret = 0;
    unsigned char dev_buf[64] = {0}; 
    ret = copy_from_user(dev_buf, ubuf, size );
    if(ret < 0){
        printk("读取失败!!\r\n");
        return -1;
    }
    if(dev_buf[0] == 0)
        gpio_set_value(gpio,0);

    else
        gpio_set_value(gpio,1);
        
    return 0;
}

struct file_operations LED_fops = {
    .write = LED_write,
};

struct miscdevice led_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "LED",
    .fops = &LED_fops,
}; 

static int LED_init(void){
    int ret = 0;
    ret = platform_driver_register(&LED_platform_driver);
    if(ret <  0){
        printk("驱动注册失败\r\n");
        return -1;
    }
    ret = misc_register(&led_misc);
    if(ret < 0){
        printk("杂项设备注册失败\r\n");
        return -1;
    }
    printk("驱动加载成功\r\n");
    return 0;
}

static void LED_exit(void){
    platform_driver_unregister( &LED_platform_driver);
    misc_deregister(&led_misc);
    printk("驱动卸载成功\r\n");
}

module_init(LED_init);
module_exit(LED_exit);
MODULE_LICENSE("GPL");